#include "workcheck.h"
#include "ui_workcheck.h"
#include <QDebug>

using namespace cv;
using namespace std;

extern CascadeClassifier cascade;  //声明同一个分类器对象cascade
CascadeClassifier cascade_2;  //用于检测侧脸

workCheck::workCheck(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::workCheck)
{
    ui->setupUi(this);
    connect(ui->back,&QPushButton::clicked,[=](){
        emit this->back();
    });  //按返回键回到上个界面

    QTimer *pTimer = new QTimer();
    connect(pTimer, SIGNAL(timeout()), this, SLOT(showTime()));
    pTimer->start(100);  //用一个定时信号来更改时间

    //连接compare信号和槽函数
    connect(this,SIGNAL(compare()),this,SLOT(compare_face()));

}

void workCheck::showTime(){
    //获取并在LCD上输出日期和时间
    QDateTime current = QDateTime::currentDateTime();
    ui->timeShow->display(current.toString("yyyy-MM-dd  HH:mm:ss"));
}


workCheck::~workCheck()
{
    delete ui;
}

void workCheck::on_begin_clicked()
{
    //调用摄像头
    VideoCapture video;
    video.open(0);

    stop = false;
    ui->detect->setScaledContents(true);
    int sig = 0;
    int sig2 = 0;
    bool check = false;
    chrono::steady_clock::time_point startTime;
    chrono::steady_clock::time_point startTime_2;
    /*载入已训练的人脸识别算法，具体路径需要根据opencv库安装位置在config.h更改*/
    const string casPath = HAAR_PATH;
    const string casPath2 = HAAR_PATH_2;

    //检测摄像头是否成功打开
    if (!video.isOpened()) {
        qDebug() << "摄像头加载出错！";
        exit(-1);
    }

    //检测是否成功加载级联分类器
    if (!cascade.load(casPath)) {
        qDebug() << "算法加载失败！";
        exit(-1);
    }
    if (!cascade_2.load(casPath2)) {
        qDebug() << "算法加载失败！";
        exit(-1);
    }

    while (stop != true) {
        Mat vClip;
        video >> vClip;  //视频转为图像

        //若突然没有视频信号则结束
        if (vClip.empty()) {
            break;
        }

        //灰度化，减少计算
        Mat imgGray;
        cvtColor(vClip, imgGray, COLOR_BGR2GRAY);

        vector<Rect> faces(0);
        cascade.detectMultiScale(imgGray, faces, 1.1, 2, 0, Size(30, 30));  //调用人脸识别算法

        if (faces.size() > 0) {
            for (size_t i = 0; i < faces.size(); i++) {
                rectangle(vClip, faces[i], Scalar(0, 0, 255), 2, 8, 0);  //生成矩形框出人脸
            }
        }

        //未检测到人脸
        if (faces.size() == 0) {
            ui->info->setText("未识别到人脸！");
        }

        //不止一张人脸（不能确定谁打卡）
        else if (faces.size() > 1) {
            ui->info->setText("请逐个打卡！");
        }

        //只有一张人脸
        else {
            ui->info->setText("请保持不动！");
            sig++;

            //检测到只有一张人脸3秒后进行比对，其间一旦出现不是一张人脸的情况，将重新计时
            if (sig == 1) {
                startTime = chrono::steady_clock::now();
            }

            if (sig >= 3) {
                chrono::steady_clock::time_point currentTime = chrono::steady_clock::now();
                chrono::duration<double> interval = currentTime - startTime;

                if (interval.count() >= 3.0 || check == true) {
                    check = true;
                    //没有此人if...
                    //ui->info->setText("识别失败！");

                    //有此人else...

                    ui->info->setText("请转头并保持！");
                    vector<Rect> faces_2(0);
                    cascade_2.detectMultiScale(imgGray, faces_2, 1.1, 2, 0, Size(30, 30));  //调用人脸识别算法
                    if (faces_2.size() != 1) {
                        sig2 = 0;
                    }

                    //只有一张侧脸，开始计时，其间一旦出现不是一张侧脸的情况，将重新计时
                    else {
                        sig2 ++;
                        if (sig2 == 1) {
                            startTime_2 = chrono::steady_clock::now();
                        }

                        if (sig2 >= 3) {
                            chrono::steady_clock::time_point currentTime_2 = chrono::steady_clock::now();
                            chrono::duration<double> interval_2 = currentTime_2 - startTime_2;

                            //侧脸持续监测一秒以上，打卡成功
                            if (interval_2.count() >= 1.0) {
                                ui->info->setText("识别成功！");
                                check = false;
                                break;
                                //qmessagebox显示身份信息+时间，询问是否打卡？
                                    //if最近一段时间打卡过（比对数据），qmessagebox提示失败
                                    //else提示成功，记录数据
                            }
                        }
                    }
                }
            }
        }

        //转换图片格式以输出
        Mat temp;
        cvtColor(vClip,temp,COLOR_BGR2RGB);
        QImage Qtemp = QImage((const unsigned char*)(temp.data),
                                temp.cols, temp.rows, temp.step,
                                QImage::Format_RGB888);

        ui->detect->setPixmap(QPixmap::fromImage(Qtemp));  //输出检测后带框的人脸

        waitKey(1); //waitkey 1ms的延迟
        QApplication::processEvents();
    }

}

//compare信号的槽函数，暂时没有用到
void workCheck::compare_face(){

}

//停止按钮，停止检测，清屏
void workCheck::on_stop_clicked()
{
    stop = true;
    ui->info->clear();
    ui->detect->clear();
}

//返回按钮，停止检测，清屏并返回上一界面
void workCheck::on_back_clicked()
{
    stop = true;
    ui->info->clear();
    ui->detect->clear();
}
